/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1/commercial
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may use this file in compliance with the License.
 * Alternatively, if you can't copy with the License, namely if you do not
 * want to provide source code of your modifications to this file, you may
 * negotiate a commercial licence with the initial developer.
 * You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is COID.
 *
 * The Initial Developer of the Original Code is
 * PosAm.
 * Portions created by the Initial Developer are Copyright (C) 2003
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 * Brano Kemen
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

#ifndef __COID_SERVER__BSERVER_HEADER__
#define __COID_SERVER__BSERVER_HEADER__

#include "coid/comm/str.h"
#include "coid/comm/dynarray.h"
#include "coid/comm/rnd.h"

#include "coid/comm/binstream/netstreamudp.h"
//#include "baddress.h"

namespace coid {

/////////////////////////////////////////////////////////////////////////////////////
struct REQUEST_PACKET
{
    ulong arq_mag_beg;
    ulong arq_extend;
    uchar arq_type;
    charstr arq_request;
    ulong arq_mag_end;

    enum {
        MAGIC_BEG = 0xd0f0baca,
        MAGIC_END = 0x1e03bac1,

        IM_LIVE   = 0xABCDEF12,

        TYPE_IS_LIVE  = 0,
        TYPE_GET_ADDR = 1,
        TYPE_PUT_ADDR = 2,
    };

    REQUEST_PACKET() : arq_mag_beg(0), arq_extend(0), arq_type(0), arq_mag_end(0) { }

    bool is_valid() const { return ((arq_mag_beg == MAGIC_BEG) && (arq_mag_end == MAGIC_END)); }

    ulong  pack_type() const { return arq_type; }

    void reset() {
        arq_extend = arq_type = 0;
        arq_request.reset();
    }

    bool is_live(ulong _rnd) { return (arq_extend == _rnd); }

    void baddr_list_rq(const token& rq_str)
    {
        rnd_int rnd( time(0) );

        arq_mag_beg = REQUEST_PACKET::MAGIC_BEG;
        arq_mag_end = REQUEST_PACKET::MAGIC_END;
        arq_type = REQUEST_PACKET::TYPE_GET_ADDR;
        arq_extend = rnd.rand();
        arq_request = rq_str;
    }

    void baddr_update_rq(const token& rq_str)
    {
        rnd_int rnd( time(0) );

        arq_mag_beg = REQUEST_PACKET::MAGIC_BEG;
        arq_mag_end = REQUEST_PACKET::MAGIC_END;
        arq_type = REQUEST_PACKET::TYPE_PUT_ADDR;
        arq_extend = rnd.rand();
        arq_request = rq_str;
    }

    void live_test_rq()
    {
        rnd_int rnd( time(0) );

        arq_mag_beg = MAGIC_BEG;
        arq_mag_end = MAGIC_END;
        arq_type = TYPE_IS_LIVE;
        arq_extend = rnd.rand();
        arq_request = "";
    }

    friend binstream& operator << (binstream& out, const REQUEST_PACKET& t)
    {
        out << STRUCT_OPEN;
        out << t.arq_mag_beg << t.arq_extend << t.arq_type << t.arq_request << t.arq_mag_end;
        out << STRUCT_CLOSE;

        return out;
    }

    friend binstream& operator >> (binstream& in, REQUEST_PACKET& t)
    {
        in >> STRUCT_OPEN;
        in >> t.arq_mag_beg >> t.arq_extend >> t.arq_type >> t.arq_request >> t.arq_mag_end;
        in >> STRUCT_CLOSE;

        return in;
    }

};

/////////////////////////////////////////////////////////////////////////////////////
struct ADDRESSES_RESPONSE
{
    ulong arp_mag_beg;
    ulong arp_rand;
    uchar arp_type;
    dynarray<netaddr> arp_response;
    ulong arp_mag_end;

    enum {
        MAGIC = 0xFEDACABE,
        MAGIC_UPD = 0xADD0ADD0,

        TYPE_GET_ADDR = 1,
        TYPE_PUT_ADDR
    };

    ADDRESSES_RESPONSE() : arp_mag_beg(0), arp_rand(0), arp_type(0), arp_mag_end(0) { }

    void reset() {
        arp_mag_beg = arp_mag_end = arp_type = 0;
        arp_rand = 0;
        arp_response.reset();
    }

    void set_get_addr(ulong _rnd=0)
    {
        arp_mag_beg = arp_mag_end = MAGIC;
        arp_rand = _rnd;
        arp_type = TYPE_GET_ADDR;
    }

    void set_put_addr(ulong _rnd=0)
    {
        arp_mag_beg = arp_mag_end = MAGIC;
        arp_rand = _rnd;
        arp_type = TYPE_PUT_ADDR;
    }

    bool is_valid(ulong _rnd) const { return (arp_rand == _rnd) && (arp_mag_beg == MAGIC) && (arp_mag_end == MAGIC); }

    friend binstream& operator << (binstream& out, const ADDRESSES_RESPONSE& t)
    {
        out << STRUCT_OPEN;
        out << t.arp_mag_beg << t.arp_rand << t.arp_type << t.arp_response << t.arp_mag_end;
        out << STRUCT_CLOSE;

        return out;
    }

    friend binstream& operator >> (binstream& in, ADDRESSES_RESPONSE& t)
    {
        in >> STRUCT_OPEN;
        in >> t.arp_mag_beg >> t.arp_rand >> t.arp_type >> t.arp_response >> t.arp_mag_end;
        in >> STRUCT_CLOSE;

        return in;
    }

};

} // namespace coid

#endif //__COID_SERVER__BSERVER_HEADER__
